Passed
Pull Request — master (#47)
by
unknown
05:23
created

scrollspy.js ➔ _objectSpread   B

Complexity

Conditions 6

Size

Total Lines 18
Code Lines 10

Duplication

Lines 18
Ratio 100 %

Importance

Changes 0
Metric Value
cc 6
eloc 10
c 0
b 0
f 0
dl 18
loc 18
rs 8.6666
1
/*!
2
  * Bootstrap scrollspy.js v4.6.0 (https://getbootstrap.com/)
3
  * Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
4
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
5
  */
6
(function (global, factory) {
7
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery'), require('./util.js')) :
8
  typeof define === 'function' && define.amd ? define(['jquery', './util'], factory) :
0 ignored issues
show
Bug introduced by
The variable define seems to be never declared. If this is a global, consider adding a /** global: define */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
9
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.ScrollSpy = factory(global.jQuery, global.Util));
0 ignored issues
show
Bug introduced by
The variable globalThis seems to be never declared. If this is a global, consider adding a /** global: globalThis */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
Best Practice introduced by
If you intend to check if the variable self is declared in the current environment, consider using typeof self === "undefined" instead. This is safe if the variable is not actually declared.
Loading history...
Comprehensibility introduced by
Usage of the sequence operator is discouraged, since it may lead to obfuscated code.

The sequence or comma operator allows the inclusion of multiple expressions where only is permitted. The result of the sequence is the value of the last expression.

This operator is most often used in for statements.

Used in another places it can make code hard to read, especially when people do not realize it even exists as a seperate operator.

This check looks for usage of the sequence operator in locations where it is not necessary and could be replaced by a series of expressions or statements.

var a,b,c;

a = 1, b = 1,  c= 3;

could just as well be written as:

var a,b,c;

a = 1;
b = 1;
c = 3;

To learn more about the sequence operator, please refer to the MDN.

Loading history...
10
}(this, (function ($, Util) { 'use strict';
11
12
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
13
14
  var $__default = /*#__PURE__*/_interopDefaultLegacy($);
15
  var Util__default = /*#__PURE__*/_interopDefaultLegacy(Util);
16
17
  function _defineProperties(target, props) {
18
    for (var i = 0; i < props.length; i++) {
19
      var descriptor = props[i];
20
      descriptor.enumerable = descriptor.enumerable || false;
21
      descriptor.configurable = true;
22
      if ("value" in descriptor) descriptor.writable = true;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
23
      Object.defineProperty(target, descriptor.key, descriptor);
24
    }
25
  }
26
27
  function _createClass(Constructor, protoProps, staticProps) {
28
    if (protoProps) _defineProperties(Constructor.prototype, protoProps);
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
29
    if (staticProps) _defineProperties(Constructor, staticProps);
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
30
    return Constructor;
31
  }
32
33
  function _extends() {
34
    _extends = Object.assign || function (target) {
0 ignored issues
show
Comprehensibility introduced by
It seems like you are trying to overwrite a function name here. _extends is already defined in line 33 as a function. While this will work, it can be very confusing.
Loading history...
35
      for (var i = 1; i < arguments.length; i++) {
36
        var source = arguments[i];
37
38
        for (var key in source) {
0 ignored issues
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
39
          if (Object.prototype.hasOwnProperty.call(source, key)) {
40
            target[key] = source[key];
41
          }
42
        }
43
      }
44
45
      return target;
46
    };
47
48
    return _extends.apply(this, arguments);
49
  }
50
51
  /**
52
   * ------------------------------------------------------------------------
53
   * Constants
54
   * ------------------------------------------------------------------------
55
   */
56
57
  var NAME = 'scrollspy';
58
  var VERSION = '4.6.0';
59
  var DATA_KEY = 'bs.scrollspy';
60
  var EVENT_KEY = "." + DATA_KEY;
61
  var DATA_API_KEY = '.data-api';
62
  var JQUERY_NO_CONFLICT = $__default['default'].fn[NAME];
63
  var Default = {
64
    offset: 10,
65
    method: 'auto',
66
    target: ''
67
  };
68
  var DefaultType = {
69
    offset: 'number',
70
    method: 'string',
71
    target: '(string|element)'
72
  };
73
  var EVENT_ACTIVATE = "activate" + EVENT_KEY;
74
  var EVENT_SCROLL = "scroll" + EVENT_KEY;
75
  var EVENT_LOAD_DATA_API = "load" + EVENT_KEY + DATA_API_KEY;
76
  var CLASS_NAME_DROPDOWN_ITEM = 'dropdown-item';
77
  var CLASS_NAME_ACTIVE = 'active';
78
  var SELECTOR_DATA_SPY = '[data-spy="scroll"]';
79
  var SELECTOR_NAV_LIST_GROUP = '.nav, .list-group';
80
  var SELECTOR_NAV_LINKS = '.nav-link';
81
  var SELECTOR_NAV_ITEMS = '.nav-item';
82
  var SELECTOR_LIST_ITEMS = '.list-group-item';
83
  var SELECTOR_DROPDOWN = '.dropdown';
84
  var SELECTOR_DROPDOWN_ITEMS = '.dropdown-item';
85
  var SELECTOR_DROPDOWN_TOGGLE = '.dropdown-toggle';
86
  var METHOD_OFFSET = 'offset';
87
  var METHOD_POSITION = 'position';
88
  /**
89
   * ------------------------------------------------------------------------
90
   * Class Definition
91
   * ------------------------------------------------------------------------
92
   */
93
94
  var ScrollSpy = /*#__PURE__*/function () {
95
    function ScrollSpy(element, config) {
96
      var _this = this;
97
98
      this._element = element;
99
      this._scrollElement = element.tagName === 'BODY' ? window : element;
100
      this._config = this._getConfig(config);
101
      this._selector = this._config.target + " " + SELECTOR_NAV_LINKS + "," + (this._config.target + " " + SELECTOR_LIST_ITEMS + ",") + (this._config.target + " " + SELECTOR_DROPDOWN_ITEMS);
102
      this._offsets = [];
103
      this._targets = [];
104
      this._activeTarget = null;
105
      this._scrollHeight = 0;
106
      $__default['default'](this._scrollElement).on(EVENT_SCROLL, function (event) {
107
        return _this._process(event);
108
      });
109
      this.refresh();
110
111
      this._process();
112
    } // Getters
113
114
115
    var _proto = ScrollSpy.prototype;
116
117
    // Public
118
    _proto.refresh = function refresh() {
119
      var _this2 = this;
120
121
      var autoMethod = this._scrollElement === this._scrollElement.window ? METHOD_OFFSET : METHOD_POSITION;
122
      var offsetMethod = this._config.method === 'auto' ? autoMethod : this._config.method;
123
      var offsetBase = offsetMethod === METHOD_POSITION ? this._getScrollTop() : 0;
124
      this._offsets = [];
125
      this._targets = [];
126
      this._scrollHeight = this._getScrollHeight();
127
      var targets = [].slice.call(document.querySelectorAll(this._selector));
128
      targets.map(function (element) {
129
        var target;
130
        var targetSelector = Util__default['default'].getSelectorFromElement(element);
131
132
        if (targetSelector) {
133
          target = document.querySelector(targetSelector);
134
        }
135
136
        if (target) {
137
          var targetBCR = target.getBoundingClientRect();
138
139
          if (targetBCR.width || targetBCR.height) {
140
            // TODO (fat): remove sketch reliance on jQuery position/offset
141
            return [$__default['default'](target)[offsetMethod]().top + offsetBase, targetSelector];
142
          }
143
        }
144
145
        return null;
146
      }).filter(function (item) {
147
        return item;
148
      }).sort(function (a, b) {
149
        return a[0] - b[0];
150
      }).forEach(function (item) {
151
        _this2._offsets.push(item[0]);
152
153
        _this2._targets.push(item[1]);
154
      });
155
    };
156
157
    _proto.dispose = function dispose() {
158
      $__default['default'].removeData(this._element, DATA_KEY);
159
      $__default['default'](this._scrollElement).off(EVENT_KEY);
160
      this._element = null;
161
      this._scrollElement = null;
162
      this._config = null;
163
      this._selector = null;
164
      this._offsets = null;
165
      this._targets = null;
166
      this._activeTarget = null;
167
      this._scrollHeight = null;
168
    } // Private
169
    ;
170
171
    _proto._getConfig = function _getConfig(config) {
172
      config = _extends({}, Default, typeof config === 'object' && config ? config : {});
173
174
      if (typeof config.target !== 'string' && Util__default['default'].isElement(config.target)) {
175
        var id = $__default['default'](config.target).attr('id');
176
177
        if (!id) {
178
          id = Util__default['default'].getUID(NAME);
179
          $__default['default'](config.target).attr('id', id);
180
        }
181
182
        config.target = "#" + id;
183
      }
184
185
      Util__default['default'].typeCheckConfig(NAME, config, DefaultType);
186
      return config;
187
    };
188
189
    _proto._getScrollTop = function _getScrollTop() {
190
      return this._scrollElement === window ? this._scrollElement.pageYOffset : this._scrollElement.scrollTop;
191
    };
192
193
    _proto._getScrollHeight = function _getScrollHeight() {
194
      return this._scrollElement.scrollHeight || Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
195
    };
196
197
    _proto._getOffsetHeight = function _getOffsetHeight() {
198
      return this._scrollElement === window ? window.innerHeight : this._scrollElement.getBoundingClientRect().height;
199
    };
200
201
    _proto._process = function _process() {
202
      var scrollTop = this._getScrollTop() + this._config.offset;
203
204
      var scrollHeight = this._getScrollHeight();
205
206
      var maxScroll = this._config.offset + scrollHeight - this._getOffsetHeight();
207
208
      if (this._scrollHeight !== scrollHeight) {
209
        this.refresh();
210
      }
211
212
      if (scrollTop >= maxScroll) {
213
        var target = this._targets[this._targets.length - 1];
214
215
        if (this._activeTarget !== target) {
216
          this._activate(target);
217
        }
218
219
        return;
220
      }
221
222
      if (this._activeTarget && scrollTop < this._offsets[0] && this._offsets[0] > 0) {
223
        this._activeTarget = null;
224
225
        this._clear();
226
227
        return;
228
      }
229
230
      for (var i = this._offsets.length; i--;) {
231
        var isActiveTarget = this._activeTarget !== this._targets[i] && scrollTop >= this._offsets[i] && (typeof this._offsets[i + 1] === 'undefined' || scrollTop < this._offsets[i + 1]);
232
233
        if (isActiveTarget) {
234
          this._activate(this._targets[i]);
235
        }
236
      }
237
    };
238
239
    _proto._activate = function _activate(target) {
240
      this._activeTarget = target;
241
242
      this._clear();
243
244
      var queries = this._selector.split(',').map(function (selector) {
245
        return selector + "[data-target=\"" + target + "\"]," + selector + "[href=\"" + target + "\"]";
246
      });
247
248
      var $link = $__default['default']([].slice.call(document.querySelectorAll(queries.join(','))));
249
250
      if ($link.hasClass(CLASS_NAME_DROPDOWN_ITEM)) {
251
        $link.closest(SELECTOR_DROPDOWN).find(SELECTOR_DROPDOWN_TOGGLE).addClass(CLASS_NAME_ACTIVE);
252
        $link.addClass(CLASS_NAME_ACTIVE);
253
      } else {
254
        // Set triggered link as active
255
        $link.addClass(CLASS_NAME_ACTIVE); // Set triggered links parents as active
256
        // With both <ul> and <nav> markup a parent is the previous sibling of any nav ancestor
257
258
        $link.parents(SELECTOR_NAV_LIST_GROUP).prev(SELECTOR_NAV_LINKS + ", " + SELECTOR_LIST_ITEMS).addClass(CLASS_NAME_ACTIVE); // Handle special case when .nav-link is inside .nav-item
259
260
        $link.parents(SELECTOR_NAV_LIST_GROUP).prev(SELECTOR_NAV_ITEMS).children(SELECTOR_NAV_LINKS).addClass(CLASS_NAME_ACTIVE);
261
      }
262
263
      $__default['default'](this._scrollElement).trigger(EVENT_ACTIVATE, {
264
        relatedTarget: target
265
      });
266
    };
267
268
    _proto._clear = function _clear() {
269
      [].slice.call(document.querySelectorAll(this._selector)).filter(function (node) {
270
        return node.classList.contains(CLASS_NAME_ACTIVE);
271
      }).forEach(function (node) {
272
        return node.classList.remove(CLASS_NAME_ACTIVE);
273
      });
274
    } // Static
275
    ;
276
277 View Code Duplication
    ScrollSpy._jQueryInterface = function _jQueryInterface(config) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
278
      return this.each(function () {
279
        var data = $__default['default'](this).data(DATA_KEY);
280
281
        var _config = typeof config === 'object' && config;
282
283
        if (!data) {
284
          data = new ScrollSpy(this, _config);
285
          $__default['default'](this).data(DATA_KEY, data);
286
        }
287
288
        if (typeof config === 'string') {
289
          if (typeof data[config] === 'undefined') {
290
            throw new TypeError("No method named \"" + config + "\"");
291
          }
292
293
          data[config]();
294
        }
295
      });
296
    };
297
298
    _createClass(ScrollSpy, null, [{
299
      key: "VERSION",
300
      get: function get() {
301
        return VERSION;
302
      }
303
    }, {
304
      key: "Default",
305
      get: function get() {
306
        return Default;
307
      }
308
    }]);
309
310
    return ScrollSpy;
311
  }();
312
  /**
313
   * ------------------------------------------------------------------------
314
   * Data Api implementation
315
   * ------------------------------------------------------------------------
316
   */
317
318
319
  $__default['default'](window).on(EVENT_LOAD_DATA_API, function () {
320
    var scrollSpys = [].slice.call(document.querySelectorAll(SELECTOR_DATA_SPY));
321
    var scrollSpysLength = scrollSpys.length;
322
323
    for (var i = scrollSpysLength; i--;) {
324
      var $spy = $__default['default'](scrollSpys[i]);
325
326
      ScrollSpy._jQueryInterface.call($spy, $spy.data());
327
    }
328
  });
329
  /**
330
   * ------------------------------------------------------------------------
331
   * jQuery
332
   * ------------------------------------------------------------------------
333
   */
334
335
  $__default['default'].fn[NAME] = ScrollSpy._jQueryInterface;
336
  $__default['default'].fn[NAME].Constructor = ScrollSpy;
337
338
  $__default['default'].fn[NAME].noConflict = function () {
339
    $__default['default'].fn[NAME] = JQUERY_NO_CONFLICT;
340
    return ScrollSpy._jQueryInterface;
341
  };
342
343
  return ScrollSpy;
344
345
})));
346
//# sourceMappingURL=scrollspy.js.map
347